package cn.tedu.vue_master.security;


import cn.tedu.vue_master.pojo.Constants;
import cn.tedu.vue_master.pojo.user.UserInfo;
import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * JWT工具类
 */
@Slf4j
@Component("JwtTokenUtils")
public class JwtTokenUtils {
    //自定义载荷的key值
    private static final String CLAIM_KEY_USERNAME = "sub";
    private static final String CLAIM_KEY_CREATED = "created";
    private static final ObjectMapper objectMapper = new ObjectMapper();

    /**
     * JWT工具生成Token active=true
     */
    private String generateToken(Map<String, Object> claims) {
        String token = Jwts.builder()
                .setClaims(claims)//自定义载荷
                .setExpiration(generateExpirationDate()) // 默认载荷属性过期时间
                .signWith(SignatureAlgorithm.HS512, Constants.SECRET_KEY) // 签名算法,和签名密码
                .compact();
        log.info("根据载荷，hash算法，和密码生成有效Token：{}", token);
        return token;
    }

    /**
     * 生成Token的过期时间 active=true
     */
    private Date generateExpirationDate() {
        Date date = new Date(System.currentTimeMillis() + Constants.EXPIRATION);
        log.info("生成token时，生成过期时间值：{}", date);
        return date;
    }

    /**
     * 从JWT Token获取载荷,包括自定义和默认所有内容 active=true
     */
    private Claims getClaimsFromToken(String token) {
        Claims claims = null;
        try {
            claims = Jwts.parser()
                    .setSigningKey(Constants.SECRET_KEY)
                    .parseClaimsJws(token)
                    .getBody();
            log.info("当需要解析Token时，获取载荷");
        } catch (Exception e) {
            log.info("JWT格式验证失败：{}", token);
        }
        return claims;
    }

    public UserInfo getMyUserDetails(String authToken) {
        Claims claims=null;
        UserInfo userInfo = new UserInfo();
        try {
            claims = getClaimsFromToken(authToken);
            log.debug("claims = {}", claims);
            if(claims==null){
                return null;
            }
        } catch (NullPointerException e) {
            log.info("Token解析失败，当前Token完全无效，无法解析数据！", e);
            return null;
        }

        // 拿到载荷之后，解析userDetails对象
        try {
            String userId = claims.get("userId", String.class); // 新增
            log.debug("从JWT中解析得到【id】的值：{}", userId); // 新增
            String userName = claims.get("userName", String.class);
            log.debug("从JWT中解析得到【username】的值：{}", userName);
            String exp = claims.get("exp", Date.class).toString();
            log.debug("从JWT中解析得到【exp】的值：{}", exp);
            String authorityListString = claims.get("authorities", String.class); // 新增
            log.debug("从JWT中解析得到【authorities】的值：{}", authorityListString); // 新增
            // 准备权限，将封装到认证信息中
            List<SimpleGrantedAuthority> authorityList
                    = JSON.parseArray(authorityListString, SimpleGrantedAuthority.class);
            userInfo.setUserId(userId);
            userInfo.setUserName(userName);
            userInfo.setAuthorities(authorityList);
            return userInfo;
        } catch (Exception e) {
            log.info("尝试解析token为userDetails失败",e);
            return null;
        }
    }
}
